"""
@file: login.py
@author: lingdubing
@time: 2024/10/31  14:11
@desc: 登录及注册路由
@character: utf-8
@contain: [register, login, get_code]
"""

from fastapi import APIRouter, Depends
from models.models import User, UserRoleLink
from schemas.login_model import RegisterModel, LoginModel
from schemas.response import *
from core.Utils import generate_uuid, en_password, generate_code, send_code, check_password
from sqlmodel import Session, select
from database.mysql import engine
from database.redis import code_cache
from aioredis import Redis
from config import settings
from core.Auth import generate_token

router = APIRouter()


@router.get("/getcode", summary="用户获取验证码", response_model=ReturnNoneDataModel)
async def get_code(username: str):
    """
    获取验证码
    :param username: 用户名
    :return: 验证码
    """
    cache: Redis = await code_cache()

    code = generate_code()
    # 设置redis时长为90秒
    await cache.set(username, code)
    await cache.expire(username, 90)
    result = send_code(username, code)
    if str(result) == "0":
        return ReturnNoneDataModel(code=STATUS_CODE["success"], message="验证码发送成功", success=True)
    else:
        exp = settings.MSGSTATUSSTR[str(result)]
        return ReturnNoneDataModel(code=STATUS_CODE["success"], message=f"验证码发送失败,异常在{exp}", success=False)


@router.post("/register", summary="用户注册", response_model=ReturnNoneDataModel)
async def register(user: RegisterModel):
    """
    用户注册
    :param user: 用户信息
    :return: 注册结果
    """

    # 查询redis数据库里是否存在该用户名的验证码并验证
    cache: Redis = await code_cache()
    if not await cache.exists(user.username):
        return ReturnNoneDataModel(code=STATUS_CODE["method_not_allowed"], message="验证码已过期", success=True)
    redis_code = await cache.get(user.username)
    if redis_code != user.ver_code:
        return ReturnNoneDataModel(code=STATUS_CODE["method_not_allowed"], message="验证码错误", success=True)
    # 删除redis数据库里该用户名的验证码
    await cache.delete(user.username)
    # 查询数据库中是否存在该用户名
    with Session(engine) as session:
        user_info = session.exec(select(User).where(User.username == user.username)).first()
        if user_info:
            return ReturnNoneDataModel(code=STATUS_CODE["method_not_allowed"], message="该账号已注册过", success=True)

        # 生成用户 ID 和加密密码
        user_id = generate_uuid()
        hashed_password = en_password(user.password)

        # 创建新用户
        new_user = User(user_id=user_id, username=user.username, password=hashed_password)
        session.add(new_user)
        session.commit()
        session.refresh(new_user)

        # 给新用户分配一个普通用户的角色
        default_role_id = settings.ROLE_DICT["user"]
        new_user_role = UserRoleLink(user_id=new_user.user_id, role_id=default_role_id)
        session.add(new_user_role)
        session.commit()

        return ReturnNoneDataModel(code=STATUS_CODE["success"], message="注册成功", success=True)


@router.post("/login", summary="用户登录", response_model=ReturnNoneDataModel)
async def login(user: LoginModel):
    """
    用户登录
    :param user:
    :return:
    """

    with Session(engine) as session:
        user_info = session.exec(select(User).where(User.username == user.username)).first()
        if user_info is None or user_info.user_status == 0:
            return ReturnNoneDataModel(code=STATUS_CODE["method_not_allowed"], message="该账号密码错误或已被禁用",
                                       success=False)
    # 查询redis数据库里是否存在该用户名的验证码并验证
    if user.ver_code is None and user.password is None:
        return ReturnNoneDataModel(code=STATUS_CODE["method_not_allowed"], message="该账号密码错误或已被禁用",
                                   success=False)
    cache: Redis = await code_cache()
    if user.ver_code is not None:
        if not await cache.exists(user.username):
            return ReturnNoneDataModel(code=STATUS_CODE["method_not_allowed"], message="验证码已过期", success=False)
        redis_code = await cache.get(user.username)
        if redis_code != user.ver_code:
            return ReturnNoneDataModel(code=STATUS_CODE["method_not_allowed"], message="验证码错误", success=False)
        token = generate_token(user.username)
        await cache.delete(user.username)
        return ReturnNoneDataModel(code=STATUS_CODE["success"], message=f"{token}", success=True)
    if user.password is not None:
        check_result = check_password(user.password, user_info.password)
        if check_result:
            token = generate_token(user.username)
            return ReturnNoneDataModel(code=STATUS_CODE["success"], message=f"{token}", success=True)
        else:
            return ReturnNoneDataModel(code=STATUS_CODE["method_not_allowed"], message="该账号密码错误或已被禁用",
                                       success=False)


